package com.file.parser.socialsecurity;

import com.file.bo.ResponseData;
import com.file.bo.socialsecurity.SichuangIndividualRecordSheet;
import com.file.bo.socialsecurity.SichuangInsuranceParticipation;
import com.file.constant.ErrorCode;
import com.file.parser.BasePdfParser;
import com.file.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import technology.tabula.*;
import technology.tabula.detectors.SpreadsheetDetectionAlgorithm;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Slf4j
public class SichuangSocialSecurityPdfParser extends BasePdfParser {

    public ResponseData<String> parseSichuangSocialSecurityPdfToJson(String daId, String filePath) {
        log.info("parseSichuangSocialSecurityPdfToJson started, daId:{}", daId);
        String json = null;
        try {
            if (filePath.contains("cbzm")) {
                SichuangInsuranceParticipation sichuangInsuranceParticipation = parseSichuangInsuranceParticipation(filePath);
                json = JsonUtils.convertObjectToJson(sichuangInsuranceParticipation);
            } else if (filePath.contains("qyd")) {
                SichuangIndividualRecordSheet sichuangIndividualRecordSheet = parseSichuangIndividualRecordSheet(filePath);
                json = JsonUtils.convertObjectToJson(sichuangIndividualRecordSheet);
            } else {
                log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseSichuangSocialSecurityPdfToJson failed, new type not supported");
                return new ResponseData<>(null, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
            }
        } catch (Exception e) {
            log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseSichuangSocialSecurityPdfToJson failed", e);
            return new ResponseData<>(null, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
        }

        log.info("parseSichuangSocialSecurityPdfToJson completed, daId:{}", daId);
        return new ResponseData<>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
    }

    private SichuangInsuranceParticipation parseSichuangInsuranceParticipation (String filePath) {
        SichuangInsuranceParticipation sichuangInsuranceParticipation = parseInsuranceParticipationHeader(filePath);
        Map<Integer, List<List<String>>> rowMap = parseFileToRowList(filePath);
        List<List<String>> rowList = new ArrayList<>();
        rowMap.values().forEach(rowList::addAll);
        parseListToBO(rowList, sichuangInsuranceParticipation);

        return sichuangInsuranceParticipation;
    }

    private SichuangIndividualRecordSheet parseSichuangIndividualRecordSheet(String filePath) {
        SichuangIndividualRecordSheet sichuangIndividualRecordSheet = parseIndividualRecordSheetHeader(filePath);
        Map<Integer, List<List<String>>> rowMap = parseFileToRowList(filePath);
        parseListToBO(rowMap, sichuangIndividualRecordSheet);

        return sichuangIndividualRecordSheet;
    }

    private SichuangIndividualRecordSheet parseIndividualRecordSheetHeader (String filePath) {
        SichuangIndividualRecordSheet sichuangIndividualRecordSheet = new SichuangIndividualRecordSheet();
        String pdfHeader = getPdfTextByStripper(filePath).replace(System.getProperty("line.separator", "\n"), "");

        String recordPeriod = pdfHeader.substring(pdfHeader.indexOf("权益信息表（") + 6, pdfHeader.indexOf("）")).trim();
        recordPeriod = removeSpaces(recordPeriod);
        recordPeriod = recordPeriod.replaceAll("\\D", "");
        sichuangIndividualRecordSheet.setRecordPeriod(recordPeriod + "年1月至" + recordPeriod + "年12月");
        String verifyDescription = pdfHeader.substring(pdfHeader.indexOf("说明：") + 3).trim();
        sichuangIndividualRecordSheet.setVerifyDescription(verifyDescription);
        String printTime = pdfHeader.substring(pdfHeader.indexOf("打印时间") + 5, pdfHeader.indexOf("说明：")).trim();
        sichuangIndividualRecordSheet.setPrintTime(printTime);
        return sichuangIndividualRecordSheet;
    }

    private void parseListToBO(List<List<String>> rowList, SichuangInsuranceParticipation sichuangInsuranceParticipation) {
        String sectionName = "";
        List<SichuangInsuranceParticipation.CalendarYearInsuranceParticipationRecord> calendarYearList = new ArrayList<>();
        List<SichuangInsuranceParticipation.PastTwoYearInsuranceParticipationRecord> pastTwoYearList = new ArrayList<>();
        boolean hasSecondaryUnitCode = false;

        for (List<String> cellList : rowList) {
            if (StringUtils.equalsAny(cellList.get(0), "险种")) {
                sectionName = "险种";
                continue;
            } else if (StringUtils.equalsAny(cellList.get(1), "单位:元")) {
                continue;
            } else if (StringUtils.equalsAny(cellList.get(0), "缴费月份")) {
                sectionName = "缴费月份";
                if (StringUtils.equalsAny(cellList.get(2), "二级单位编码")) {
                    hasSecondaryUnitCode = true;
                }
                continue;
            } else if (StringUtils.equalsAny(cellList.get(0), "四川省社会保险个人参保证明", "说明", "(二)最近两年的参保缴费明细")) {
                continue;
            }

            switch (sectionName) {//NOSONAR
                case "险种":
                    if (StringUtils.isBlank(cellList.get(0))) {
                        break;
                    }
                    SichuangInsuranceParticipation.CalendarYearInsuranceParticipationRecord calendarYear = new SichuangInsuranceParticipation.CalendarYearInsuranceParticipationRecord();
                    calendarYear.setType(cellList.get(0));
                    calendarYear.setCurrentPaymentStatus(cellList.get(1));
                    calendarYear.setTotalMonth(cellList.get(2));
                    calendarYearList.add(calendarYear);
                    break;
                case "缴费月份":
                    if (StringUtils.isBlank(cellList.get(0)) || StringUtils.equals("说明:", cellList.get(0))) {
                        break;
                    }
                    SichuangInsuranceParticipation.PastTwoYearInsuranceParticipationRecord pastTwoYear = new SichuangInsuranceParticipation.PastTwoYearInsuranceParticipationRecord();
                    pastTwoYear.setPaymentMonth(cellList.get(0));
                    pastTwoYear.setInsuredUnitCode(cellList.get(1));
                    pastTwoYear.setSecondaryUnitCode(hasSecondaryUnitCode ? cellList.get(2) : "");

                    SichuangInsuranceParticipation.EndowmentInsurance endowmentInsurance = new SichuangInsuranceParticipation.EndowmentInsurance();
                    endowmentInsurance.setType(hasSecondaryUnitCode ? cellList.get(3) : cellList.get(2));
                    endowmentInsurance.setPaymentBase(hasSecondaryUnitCode ? cellList.get(4) : cellList.get(3));
                    endowmentInsurance.setUnitPayment(hasSecondaryUnitCode ? cellList.get(5) : cellList.get(4));
                    endowmentInsurance.setPersonalPayment(hasSecondaryUnitCode ? cellList.get(6) : cellList.get(5));
                    pastTwoYear.setEndowmentInsurance(endowmentInsurance);

                    SichuangInsuranceParticipation.UnemploymentInsurance unemploymentInsurance = new  SichuangInsuranceParticipation.UnemploymentInsurance();
                    unemploymentInsurance.setPaymentBase(hasSecondaryUnitCode ? cellList.get(7) : cellList.get(6));
                    unemploymentInsurance.setUnitPayment(hasSecondaryUnitCode ? cellList.get(8) : cellList.get(7));
                    unemploymentInsurance.setPersonalPayment(hasSecondaryUnitCode ? cellList.get(9) : cellList.get(8));
                    pastTwoYear.setUnemploymentInsurance(unemploymentInsurance);

                    SichuangInsuranceParticipation.EmploymentInjuryInsurance employmentInjuryInsurance = new SichuangInsuranceParticipation.EmploymentInjuryInsurance();
                    employmentInjuryInsurance.setPaymentBase(hasSecondaryUnitCode ? cellList.get(10) : cellList.get(9));
                    employmentInjuryInsurance.setUnitPayment(hasSecondaryUnitCode ? cellList.get(11) : cellList.get(10));
                    pastTwoYear.setEmploymentInjuryInsurance(employmentInjuryInsurance);

                    pastTwoYear.setPaymentLocation(hasSecondaryUnitCode ? cellList.get(12) : cellList.get(11));
                    pastTwoYearList.add(pastTwoYear);
                    break;
            }
        }
        sichuangInsuranceParticipation.setCalendarYearInsuranceParticipationRecordList(calendarYearList);
        sichuangInsuranceParticipation.setPastTwoYearInsuranceParticipationRecordList(pastTwoYearList);
    }

    private void parseListToBO(Map<Integer, List<List<String>>> rowMap, SichuangIndividualRecordSheet sichuangIndividualRecordSheet) {
        String sectionName = "";
        SichuangIndividualRecordSheet.PersonalBasicInformation personalBasicInformation = new SichuangIndividualRecordSheet.PersonalBasicInformation();
        List<SichuangIndividualRecordSheet.WorkersYearPaymentStatusOfUrbanEmployeeInsuredPersons> workersYearPaymentList = new ArrayList<>();
        List<SichuangIndividualRecordSheet.ResidentYearPaymentStatusOfUrbanEmployeeInsuredPersons> residentYearPaymentList = new ArrayList<>();
        List<SichuangIndividualRecordSheet.PersonalAccountInformationOfPensionInsurance> personalAccountList = new ArrayList<>();


        // 解析pdf第一页的表格
        for (int i = 0; i < rowMap.get(1).size(); i++) {
            List<String> cellList = rowMap.get(1).get(i);
            if (StringUtils.equals(cellList.get(0), "姓名")) {
                sectionName = "姓名";
            } else if (StringUtils.equalsAny(cellList.get(0), "证件类型")) {
                sectionName = "证件类型";
            } else if (StringUtils.equalsAny(cellList.get(0), "本地首次参保年月")) {
                sectionName = "本地首次参保年月";
                continue;
            } else if (StringUtils.equalsAny(cellList.get(0), "城镇职工参保人员本年度缴费情况")) {
                sectionName = "城镇职工参保人员本年度缴费情况";
                continue;
            } else if (StringUtils.equalsAny(cellList.get(0), "城乡居民参保人员本年度缴费情况")) {
                sectionName = "城乡居民参保人员本年度缴费情况";
                continue;
            } else if (StringUtils.equalsAny(cellList.get(0), "养老保险个人账户情况")) {
                sectionName = "养老保险个人账户情况";
                continue;
            } else if (StringUtils.equalsAny(cellList.get(0), "序号")){
                continue;
            }

            switch (sectionName) {//NOSONAR
                case "姓名" :
                    personalBasicInformation.setName(cellList.get(1));
                    personalBasicInformation.setGender(cellList.get(3));
                    personalBasicInformation.setSocialSecurityNumber(cellList.get(5));
                    break;
                case "证件类型" :
                    personalBasicInformation.setIdType(cellList.get(1));
                    personalBasicInformation.setIdNo(removeSpaces(cellList.get(3)));
                    break;
                case "本地首次参保年月":
                    SichuangIndividualRecordSheet.LocalInsuranceYearMonth localInsuranceYearMonth = new SichuangIndividualRecordSheet.LocalInsuranceYearMonth();
                    localInsuranceYearMonth.setEnterpriseWorkPension(removeSpaces(cellList.get(1)));
                    localInsuranceYearMonth.setCauseWorkPension(removeSpaces(cellList.get(2)));
                    localInsuranceYearMonth.setUrbanResidentsPension(removeSpaces(cellList.get(3)));
                    localInsuranceYearMonth.setInjuryInsurance(removeSpaces(cellList.get(4)));
                    localInsuranceYearMonth.setUnemploymentInsurance(removeSpaces(cellList.get(5)));
                    personalBasicInformation.setLocalInsuranceYearMonth(localInsuranceYearMonth);
                    break;
                case "城镇职工参保人员本年度缴费情况" :
                    SichuangIndividualRecordSheet.WorkersYearPaymentStatusOfUrbanEmployeeInsuredPersons workersYearPayment = new SichuangIndividualRecordSheet.WorkersYearPaymentStatusOfUrbanEmployeeInsuredPersons();
                    if (StringUtils.isBlank(cellList.get(0))) {
                        break;
                    }

                    workersYearPayment.setId(cellList.get(0));
                    workersYearPayment.setType(cellList.get(1));
                    workersYearPayment.setPaymentBaseTotal(removeSpaces(cellList.get(2)));
                    workersYearPayment.setPersonalPaymentAmount(removeSpaces(cellList.get(3)));
                    workersYearPayment.setYearPaymentMonths(removeSpaces(cellList.get(4)));
                    workersYearPayment.setTotalPaymentMonths(removeSpaces(cellList.get(5)));
                    workersYearPaymentList.add(workersYearPayment);
                    break;
                case "城乡居民参保人员本年度缴费情况" :
                    if (StringUtils.isBlank(cellList.get(0))) {
                        break;
                    }
                    SichuangIndividualRecordSheet.ResidentYearPaymentStatusOfUrbanEmployeeInsuredPersons residentYearPayment = new SichuangIndividualRecordSheet.ResidentYearPaymentStatusOfUrbanEmployeeInsuredPersons();
                    residentYearPayment.setId(cellList.get(0));
                    residentYearPayment.setType(cellList.get(1));
                    residentYearPayment.setPersonalPaymentAmount(removeSpaces(cellList.get(2)));
                    residentYearPayment.setTeamSubsidyAmount(removeSpaces(cellList.get(3)));
                    residentYearPayment.setGovernmentSubsidiesAmount(removeSpaces(cellList.get(4)));
                    residentYearPayment.setTotalPaymentYear(removeSpaces(cellList.get(5)));
                    residentYearPaymentList.add(residentYearPayment);
                    break;
                case "养老保险个人账户情况" :
                    if (StringUtils.isBlank(cellList.get(0))) {
                        break;
                    }
                    SichuangIndividualRecordSheet.PersonalAccountInformationOfPensionInsurance personalAccount = new SichuangIndividualRecordSheet.PersonalAccountInformationOfPensionInsurance();
                    personalAccount.setId(cellList.get(0));
                    personalAccount.setType(cellList.get(1));
                    personalAccount.setEndYearPrivateAccountTotalAmount(removeSpaces(cellList.get(2)));
                    personalAccount.setCurrentYearAccountingAmount(removeSpaces(cellList.get(3)));
                    personalAccount.setCurrentYearAccountingInterest(removeSpaces(cellList.get(4)));
                    personalAccount.setEndOfThisYearAccumulatedAccountStorageAmount(removeSpaces(cellList.get(5)));
                    personalAccountList.add(personalAccount);
                    break;
                default:

            }
            sichuangIndividualRecordSheet.setPersonalBasicInformation(personalBasicInformation);
            sichuangIndividualRecordSheet.setWorkersYearPaymentList(workersYearPaymentList);
            sichuangIndividualRecordSheet.setResidentYearPaymentList(residentYearPaymentList);
            sichuangIndividualRecordSheet.setPersonalAccountList(personalAccountList);
        }

    }

    private String removeSpaces (String content) {
        if (StringUtils.isBlank(content)) {
            return "";
        }
        return content.replace(" ", "");
    }

    private SichuangInsuranceParticipation parseInsuranceParticipationHeader (String filePath) {
        SichuangInsuranceParticipation sichuangInsuranceParticipation = new SichuangInsuranceParticipation();
        String pdfHeader = getPdfTextByStripper(filePath).replace(System.getProperty("line.separator", "\n"), "");
        String name = pdfHeader.substring(pdfHeader.indexOf("参保人姓名：") + 6, pdfHeader.indexOf("性别")).trim();
        sichuangInsuranceParticipation.setName(name);
        String gender = pdfHeader.substring(pdfHeader.indexOf("性别") + 3, pdfHeader.indexOf("社会保障号码")).trim();
        sichuangInsuranceParticipation.setGender(gender);
        String socialSecurityNumber = pdfHeader.substring(pdfHeader.indexOf("社会保障号码") + 7, pdfHeader.indexOf("（一）历年参保基本情况")).trim();
        sichuangInsuranceParticipation.setSocialSecurityNumber(socialSecurityNumber);
        String verifyDescription = pdfHeader.substring(pdfHeader.indexOf("说明：") + 3).trim();
        sichuangInsuranceParticipation.setVerifyDescription(verifyDescription);
        String printTime = pdfHeader.substring(pdfHeader.indexOf("打印时间") + 5, pdfHeader.indexOf("说明：")).trim();
        sichuangInsuranceParticipation.setPrintTime(printTime);
        return sichuangInsuranceParticipation;
    }

    private Map<Integer, List<List<String>>> parseFileToRowList (String filePath) {
        // 1. 读取文件
        File pdf = new File(filePath);

        //页面所有table的记录，每一个元素代表下面一条记录cellList
        Map<Integer, List<List<String>>> rowMap = new HashMap<>();

        // 2. pdfbox读取PDDocument
        try (PDDocument pdfDocument = PDDocument.load(pdf)) {
            // 3. tabula新建ObjectExtractor和NurminenDetectionAlgorithm，同时准备接收表格Rectangle的结构
            ObjectExtractor objectExtractor = new ObjectExtractor(pdfDocument);
            SpreadsheetDetectionAlgorithm detectionAlgorithm = new SpreadsheetDetectionAlgorithm();
            Map<Integer, List<Rectangle>> pageNumber2RectangleListMap = new HashMap<>();//key为页的序号， value为对应的Rectangle的list

            // 4. 获取每页的PageIterator
            PageIterator pageIterator = objectExtractor.extract();

            // 5. 解析每页的Rectangle
            // 如果单页pdf中有多个Rectangle，则解析出来的List<Rectangle>会有多个对象
            while (pageIterator.hasNext()) {
                Page page = pageIterator.next();
                List<Rectangle> rectangleList = detectionAlgorithm.detect(page);
                if (rectangleList.size() > 0) {
                    pageNumber2RectangleListMap.put(page.getPageNumber(), rectangleList);
                }
            }

            // 6.通过table位置获取表格具体内容
            SpreadsheetExtractionAlgorithm extractionAlgorithm = new SpreadsheetExtractionAlgorithm();

            // 如果单页pdf中有多个表格，则解析出来的List<Rectangle>会有多个对象
            for (Map.Entry<Integer, List<Rectangle>> entry : pageNumber2RectangleListMap.entrySet()) {
                List<List<String>> rowList = new ArrayList<>();
                Page page = objectExtractor.extract(entry.getKey());

                List<Rectangle> rectangleList = entry.getValue();
                for (Rectangle rectangle : rectangleList) {
                    if (Double.compare(rectangle.getHeight(), 0.0) == 0) {
                        continue;
                    }
                    rectangle.setBottom(rectangle.getBottom() + 10);
                    Page area = page.getArea(rectangle);
                    // 如果每页有多个表格，解析每一个table
                    List<Table> tableList = extractionAlgorithm.extract(area);
                    for (Table table : tableList) {
                        for (int i = 0; i < table.getRowCount(); i++) {
                            List<String> cellList = new ArrayList<>();//一条记录，每个单元格占一个元素
                            for (int j = 0; j < table.getColCount(); j++) {
                                cellList.add(table.getCell(i, j).getText(false));
                            }
                            rowList.add(cellList);
                        }
                    }
                    rowMap.put(page.getPageNumber(), rowList);
                }

            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        return rowMap;
    }



    public static void main(String[] args) {
        String filePath = "D:\\data\\file\\socialsecurity\\四川\\20240619\\zd4eqec41802919309066661888_2e5a2c1bdfa9ab378cea4705913f3286_app-gjzwfw-dzsb_origins\\app-gjzwfw-dzsb_qyd.pdf";
        String json;
        SichuangSocialSecurityPdfParser sichuangSocialSecurityPdfParser = new SichuangSocialSecurityPdfParser();
        json = sichuangSocialSecurityPdfParser.parseSichuangSocialSecurityPdfToJson("daId", filePath).getData();
        System.out.println(json);
    }
}
